package meta

import (
	"fmt"
	"game/game-db/orm"
	"game/game-db/orm/column"
	"game/game-db/orm/metag"
	"reflect"
	"time"
)

type SplitEntityMeta struct {
	EntityMeta
	splitWay metag.SplitWay

	splitColumn column.IColumnMeta
}

func NewSplitEntityMeta(entityStruct orm.ISplitDbEntity) *SplitEntityMeta {
	tableMetag := entityStruct.TableMetag()

	var entityMeta SplitEntityMeta
	entityMeta.fillMetaValue(entityStruct, tableMetag.TableMetag)
	entityMeta.splitWay = tableMetag.SplitWay
	entityMeta.splitColumn = entityMeta.columnsMap[tableMetag.SplitByColumn]
	return &entityMeta
}

func (t *SplitEntityMeta) SplitWay() metag.SplitWay {
	return t.splitWay
}

func (t *SplitEntityMeta) GetSplitTableName(splitValue int64) string {
	return buildTableName(t.splitWay, t.tableName, splitValue)
}

func (t *SplitEntityMeta) GetSplitTableNameByEntity(entity interface{}) string {
	splitValue := t.getSplitValue(entity)
	return buildTableName(t.splitWay, t.tableName, splitValue)
}

func (t *SplitEntityMeta) getSplitValue(entity interface{}) int64 {
	rEntity := reflect.ValueOf(entity).Elem()
	objField := rEntity.FieldByName(t.splitColumn.FieldName())
	splitValue := t.splitColumn.TakeValue(objField)
	rValue := reflect.ValueOf(splitValue)
	if rValue.Type().Name() == "Time" {
		return splitValue.(time.Time).UnixMilli()
	} else {
		return splitValue.(int64)
	}
}

func buildTableName(splitWay metag.SplitWay, tableName string, splitValue interface{}) string {
	if splitWay == metag.MINUTE {
		//年月日时分
		timeValue := splitValue.(int64)
		time := time.UnixMilli(timeValue).Format("200601021504")
		return fmt.Sprintf("%s_%s", tableName, time)
	} else if splitWay == metag.HOUR {
		//年月日时
		timeValue := splitValue.(int64)
		time := time.UnixMilli(timeValue).Format("2006010215")
		return fmt.Sprintf("%s_%s", tableName, time)
	} else if splitWay == metag.DAY {
		//年月日
		timeValue := splitValue.(int64)
		time := time.UnixMilli(timeValue).Format("20060102")
		return fmt.Sprintf("%s_%s", tableName, time)
	} else if splitWay == metag.WEEK {
		//年周
		timeValue := splitValue.(int64)
		year, week := time.UnixMilli(timeValue).ISOWeek()
		return fmt.Sprintf("%s_%d%02d", tableName, year, week)
	} else if splitWay == metag.MONTH {
		//年月
		timeValue := splitValue.(int64)
		time := time.UnixMilli(timeValue).Format("200601")
		return fmt.Sprintf("%s_%s", tableName, time)
	} else if splitWay == metag.YEAR {
		//年
		timeValue := splitValue.(int64)
		time := time.UnixMilli(timeValue).Format("2006")
		return fmt.Sprintf("%s_%s", tableName, time)
	} else if splitWay == metag.VALUE {
		//值
		value := splitValue.(int64)
		return fmt.Sprintf("%s_%v", tableName, value)
	}
	return tableName
}
